๋ฆฌ์์ค ํ ํจํด๊ณผ React Suspense๋ฅผ ํ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ ๋ฐ์ดํฐ ๋ก๋ฉ์ ์ต์ ํํ์ธ์. ๋ฐ์ดํฐ ๋ฆฌ์์ค๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ๊ณต์ ํ์ฌ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ์ ์์๋ด ๋๋ค.
React Suspense ๋ฆฌ์์ค ํ: ํจ์จ์ ์ธ ๊ณต์ ๋ฐ์ดํฐ ๋ก๋ฉ ๊ด๋ฆฌ
React Suspense๋ React 16.6์ ๋์ ๋ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ผ๋ก, ๋ฐ์ดํฐ ํ์นญ๊ณผ ๊ฐ์ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์ปดํฌ๋ํธ ๋ ๋๋ง์ "์ผ์ ์ค๋จ"ํ ์ ์๊ฒ ํด์ค๋๋ค. ์ด๋ ๋ก๋ฉ ์ํ๋ฅผ ๋ณด๋ค ์ ์ธ์ ์ด๊ณ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ๋ฌธ์ ์ด์ด์ค๋๋ค. Suspense ์์ฒด๋ ํ๋ฅญํ ๊ธฐ๋ฅ์ด์ง๋ง, ๋ฆฌ์์ค ํ(Resource Pool) ํจํด๊ณผ ๊ฒฐํฉํ๋ฉด ํนํ ์ฌ๋ฌ ์ปดํฌ๋ํธ์์ ๊ณต์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋ ํจ์ฌ ๋ ํฐ ์ฑ๋ฅ ํฅ์์ ์ด๋์ด๋ผ ์ ์์ต๋๋ค.
React Suspense ์ดํดํ๊ธฐ
๋ฆฌ์์ค ํ ํจํด์ ์ดํด๋ณด๊ธฐ ์ ์, React Suspense์ ๊ธฐ๋ณธ ์ฌํญ์ ๋น ๋ฅด๊ฒ ๋ณต์ตํด ๋ณด๊ฒ ์ต๋๋ค:
- ๋ฐ์ดํฐ ํ์นญ์ ์ํ Suspense: Suspense๋ ํ์ํ ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํด์ง ๋๊น์ง ์ปดํฌ๋ํธ ๋ ๋๋ง์ ์ผ์ ์ค์งํ ์ ์๊ฒ ํฉ๋๋ค.
- ์๋ฌ ๋ฐ์ด๋๋ฆฌ(Error Boundaries): Suspense์ ํจ๊ป ์๋ฌ ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ ํ์นญ ๊ณผ์ ์์ ๋ฐ์ํ๋ ์ค๋ฅ๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ๊ณ , ์คํจ ์ ๋์ฒด UI๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค.
- ์ปดํฌ๋ํธ ์ง์ฐ ๋ก๋ฉ(Lazy Loading): Suspense๋ ์ปดํฌ๋ํธ์ ์ง์ฐ ๋ก๋ฉ์ ๊ฐ๋ฅํ๊ฒ ํ์ฌ, ํ์ํ ๋๋ง ์ปดํฌ๋ํธ๋ฅผ ๋ก๋ํจ์ผ๋ก์จ ์ด๊ธฐ ํ์ด์ง ๋ก๋ ์๊ฐ์ ๊ฐ์ ํฉ๋๋ค.
Suspense๋ฅผ ์ฌ์ฉํ๋ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
<Suspense fallback={<p>Loading...</p>}>
<MyComponent />
</Suspense>
์ด ์์์์ MyComponent๋ ๋น๋๊ธฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ฆ์ ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์์ผ๋ฉด fallback prop, ์ด ๊ฒฝ์ฐ ๋ก๋ฉ ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ค๋น๋๋ฉด MyComponent๊ฐ ๋ ๋๋ง๋ฉ๋๋ค.
๊ณผ์ : ์ค๋ณต ๋ฐ์ดํฐ ํ์นญ
๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๋์ผํ ๋ฐ์ดํฐ์ ์์กดํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์์งํ ์ ๊ทผ ๋ฐฉ์์ ๊ฐ ์ปดํฌ๋ํธ๊ฐ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฐ์ ธ์ค๋๋ก ํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ์ค๋ณต๋ ๋ฐ์ดํฐ ํ์นญ์ผ๋ก ์ด์ด์ ธ ๋คํธ์ํฌ ๋ฆฌ์์ค๋ฅผ ๋ญ๋นํ๊ณ ์ ์ฌ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์๋๋ฅผ ์ ํ์ํฌ ์ ์์ต๋๋ค.
์ฌ์ฉ์ ์ ๋ณด๋ฅผ ํ์ํ๋ ๋์๋ณด๋๊ฐ ์๊ณ , ์ฌ์ฉ์ ํ๋กํ ์น์ ๊ณผ ์ต๊ทผ ํ๋ ํผ๋ ๋ชจ๋ ์ฌ์ฉ์์ ์ธ๋ถ ์ ๋ณด์ ์ ๊ทผํด์ผ ํ๋ ์๋๋ฆฌ์ค๋ฅผ ์๊ฐํด ๋ณด์ธ์. ๊ฐ ์ปดํฌ๋ํธ๊ฐ ์์ฒด์ ์ผ๋ก ๋ฐ์ดํฐ ํ์น๋ฅผ ์์ํ๋ฉด, ๋ณธ์ง์ ์ผ๋ก ๋์ผํ ์ ๋ณด์ ๋ํด ๋ ๋ฒ์ ๋์ผํ ์์ฒญ์ ๋ณด๋ด๋ ์ ์ ๋๋ค.
๋ฆฌ์์ค ํ ํจํด ์๊ฐ
๋ฆฌ์์ค ํ ํจํด์ ์ค์ ์ง์ค์ ๋ฐ์ดํฐ ๋ฆฌ์์ค ํ์ ์์ฑํ์ฌ ์ด ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ ์ ์ ๊ณตํฉ๋๋ค. ๊ฐ ์ปดํฌ๋ํธ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋์ , ํ์์ ๊ณต์ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ์์ฒญํฉ๋๋ค. ๋ฆฌ์์ค๊ฐ ์ด๋ฏธ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฒฝ์ฐ(์ฆ, ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ํ์น๋ ๊ฒฝ์ฐ) ์ฆ์ ๋ฐํ๋ฉ๋๋ค. ๋ฆฌ์์ค๊ฐ ์์ง ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์์ ๊ฒฝ์ฐ, ํ์ ๋ฐ์ดํฐ ํ์น๋ฅผ ์์ํ๊ณ ์๋ฃ๋๋ฉด ๋ชจ๋ ์์ฒญ ์ปดํฌ๋ํธ์ ์ด๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ด ํจํด์ ์ฌ๋ฌ ๊ฐ์ง ์ฅ์ ์ ์ ๊ณตํฉ๋๋ค:
- ์ค๋ณต ํ์นญ ๊ฐ์: ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ์๋ก ํ๋๋ผ๋ ๋ฐ์ดํฐ๊ฐ ํ ๋ฒ๋ง ํ์น๋๋๋ก ๋ณด์ฅํฉ๋๋ค.
- ์ฑ๋ฅ ํฅ์: ๋คํธ์ํฌ ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ณ ์ ๋ฐ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ์ค์ ์ง์ค์ ๋ฐ์ดํฐ ๊ด๋ฆฌ: ๋ฐ์ดํฐ์ ๋ํ ๋จ์ผ ์ง์ค ๊ณต๊ธ์(single source of truth)์ ์ ๊ณตํ์ฌ ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ์ผ๊ด์ฑ์ ๋จ์ํํฉ๋๋ค.
React Suspense๋ก ๋ฆฌ์์ค ํ ๊ตฌํํ๊ธฐ
React Suspense๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค ํ ํจํด์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ๋ฆฌ์์ค ํฉํ ๋ฆฌ ์์ฑ: ์ด ํฉํ ๋ฆฌ ํจ์๋ ๋ฐ์ดํฐ ํ์นญ ํ๋ก๋ฏธ์ค(promise)๋ฅผ ์์ฑํ๊ณ Suspense์ ํ์ํ ์ธํฐํ์ด์ค๋ฅผ ๋ ธ์ถํ๋ ์ญํ ์ ํฉ๋๋ค.
- ๋ฆฌ์์ค ํ ๊ตฌํ: ํ์ ์์ฑ๋ ๋ฆฌ์์ค๋ฅผ ์ ์ฅํ๊ณ ๊ทธ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ๋ํ ๊ฐ ๊ณ ์ ๋ฆฌ์์ค์ ๋ํด ๋จ ํ๋์ ํ์น๋ง ์์๋๋๋ก ๋ณด์ฅํฉ๋๋ค.
- ์ปดํฌ๋ํธ์์ ๋ฆฌ์์ค ์ฌ์ฉ: ์ปดํฌ๋ํธ๋ ํ์์ ๋ฆฌ์์ค๋ฅผ ์์ฒญํ๊ณ
React.use๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ ๋๋ง์ ์ผ์ ์ค๋จํฉ๋๋ค.
1. ๋ฆฌ์์ค ํฉํ ๋ฆฌ ์์ฑํ๊ธฐ
๋ฆฌ์์ค ํฉํ ๋ฆฌ๋ ๋ฐ์ดํฐ ํ์นญ ํจ์๋ฅผ ์
๋ ฅ์ผ๋ก ๋ฐ์ React.use์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค. ์ด ๊ฐ์ฒด๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๊ฑฐ๋, ๋ฐ์ดํฐ๊ฐ ์์ง ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์์ ๊ฒฝ์ฐ ํ๋ก๋ฏธ์ค๋ฅผ ๋์ง๋(throw) read ๋ฉ์๋๋ฅผ ๊ฐ์ง๋๋ค.
function createResource(fetchData) {
let status = 'pending';
let result;
let suspender = fetchData().then(
(r) => {
status = 'success';
result = r;
},
(e) => {
status = 'error';
result = e;
}
);
return {
read() {
if (status === 'pending') {
throw suspender;
} else if (status === 'error') {
throw result;
} else if (status === 'success') {
return result;
}
},
};
}
์ค๋ช :
createResourceํจ์๋fetchDataํจ์๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ต๋๋ค. ์ด ํจ์๋ ๋ฐ์ดํฐ๋ก resolve๋๋ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค.status๋ณ์๋ ๋ฐ์ดํฐ ํ์นญ ์ํ('pending','success','error')๋ฅผ ์ถ์ ํฉ๋๋ค.suspender๋ณ์๋fetchData๊ฐ ๋ฐํํ ํ๋ก๋ฏธ์ค๋ฅผ ๋ณด์ ํฉ๋๋ค.then๋ฉ์๋๋ ํ๋ก๋ฏธ์ค๊ฐ resolve๋๊ฑฐ๋ reject๋ ๋status์result๋ณ์๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.read๋ฉ์๋๋ Suspense์ ํตํฉํ๋ ํต์ฌ์ ๋๋ค.status๊ฐ'pending'์ด๋ฉดsuspenderํ๋ก๋ฏธ์ค๋ฅผ ๋์ ธ Suspense๊ฐ ๋ ๋๋ง์ ์ผ์ ์ค๋จํ๋๋ก ํฉ๋๋ค.status๊ฐ'error'์ด๋ฉด ์๋ฌ๋ฅผ ๋์ ธ ์๋ฌ ๋ฐ์ด๋๋ฆฌ๊ฐ ์ด๋ฅผ ์ก์ ์ ์๊ฒ ํฉ๋๋ค.status๊ฐ'success'์ด๋ฉด ๋ฐ์ดํฐ๋ฅผ ๋ฐํํฉ๋๋ค.
2. ๋ฆฌ์์ค ํ ๊ตฌํํ๊ธฐ
๋ฆฌ์์ค ํ์ ์์ฑ๋ ๋ฆฌ์์ค๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๋ ์ญํ ์ ํฉ๋๋ค. ๊ฐ ๊ณ ์ ๋ฆฌ์์ค์ ๋ํด ๋จ ํ๋์ ํ์น๋ง ์์๋๋๋ก ๋ณด์ฅํฉ๋๋ค.
const resourcePool = {
cache: new Map(),
get(key, fetchData) {
if (!this.cache.has(key)) {
this.cache.set(key, createResource(fetchData));
}
return this.cache.get(key);
},
};
์ค๋ช :
resourcePool๊ฐ์ฒด๋ ์์ฑ๋ ๋ฆฌ์์ค๋ฅผ ์ ์ฅํ๋Map์ธcache์์ฑ์ ๊ฐ์ง๋๋ค.get๋ฉ์๋๋key์fetchDataํจ์๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ต๋๋ค.key๋ ๋ฆฌ์์ค๋ฅผ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.- ๋ฆฌ์์ค๊ฐ ์บ์์ ์์ง ์์ผ๋ฉด
createResourceํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ๊ณ ์บ์์ ์ถ๊ฐํฉ๋๋ค. - ๊ทธ๋ฐ ๋ค์
get๋ฉ์๋๋ ์บ์์์ ๋ฆฌ์์ค๋ฅผ ๋ฐํํฉ๋๋ค.
3. ์ปดํฌ๋ํธ์์ ๋ฆฌ์์ค ์ฌ์ฉํ๊ธฐ
์ด์ React ์ปดํฌ๋ํธ์์ ๋ฆฌ์์ค ํ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. React.use ํ
์ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค์์ ๋ฐ์ดํฐ์ ์ ๊ทผํ์ธ์. ๋ฐ์ดํฐ๊ฐ ์์ง ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์์ ๊ฒฝ์ฐ ์ปดํฌ๋ํธ๋ฅผ ์๋์ผ๋ก ์ผ์ ์ค๋จํฉ๋๋ค.
import React from 'react';
function MyComponent({ userId }) {
const userResource = resourcePool.get(userId, () => fetchUser(userId));
const user = React.use(userResource).user;
return (
<div>
<h2>User Profile</h2>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
</div>
);
}
function fetchUser(userId) {
return fetch(`https://api.example.com/users/${userId}`).then((response) =>
response.json()
).then(data => ({user: data}));
}
export default MyComponent;
์ค๋ช :
MyComponent์ปดํฌ๋ํธ๋userIdprop์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ต๋๋ค.resourcePool.get๋ฉ์๋๋ ํ์์ ์ฌ์ฉ์ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.key๋userId์ด๊ณ ,fetchDataํจ์๋fetchUser์ ๋๋ค.React.useํ ์userResource์์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์์ง ์ฌ์ฉ ๊ฐ๋ฅํ์ง ์์ ๊ฒฝ์ฐ ์ด ํ ์ด ์ปดํฌ๋ํธ๋ฅผ ์ผ์ ์ค๋จํฉ๋๋ค.- ๊ทธ๋ฐ ๋ค์ ์ปดํฌ๋ํธ๋ ์ฌ์ฉ์์ ์ด๋ฆ๊ณผ ์ด๋ฉ์ผ์ ๋ ๋๋งํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก, ๋ก๋ฉ ์ํ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ปดํฌ๋ํธ๋ฅผ <Suspense>๋ก ๊ฐ์ธ์ค๋๋ค:
<Suspense fallback={<p>Loading user profile...</p>}>
<MyComponent userId={123} />
</Suspense>
๊ณ ๊ธ ๊ณ ๋ ค์ฌํญ
์บ์ ๋ฌดํจํ
์ค์ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ๊ฐ ์ ๋ฐ์ดํธ๋ ๋ ์บ์๋ฅผ ๋ฌดํจํํ๋ ๋ฉ์ปค๋์ฆ์ด ํ์ํฉ๋๋ค. ์ฌ๊ธฐ์๋ ํ์์ ๋ฆฌ์์ค๋ฅผ ์ ๊ฑฐํ๊ฑฐ๋ ๋ฆฌ์์ค ๋ด์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๊ฒ์ด ํฌํจ๋ ์ ์์ต๋๋ค.
resourcePool.invalidate = (key) => {
resourcePool.cache.delete(key);
};
์ค๋ฅ ์ฒ๋ฆฌ
Suspense๋ ๋ก๋ฉ ์ํ๋ฅผ ์ฐ์ํ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ฒ ํด์ฃผ์ง๋ง, ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ฒ๋ ๋๊ฐ์ด ์ค์ํฉ๋๋ค. ๋ฐ์ดํฐ ํ์นญ ๋๋ ๋ ๋๋ง ์ค์ ๋ฐ์ํ๋ ๋ชจ๋ ์ค๋ฅ๋ฅผ ์ก๊ธฐ ์ํด ์ปดํฌ๋ํธ๋ฅผ ์๋ฌ ๋ฐ์ด๋๋ฆฌ๋ก ๊ฐ์ธ์ธ์.
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// ๋ค์ ๋ ๋๋ง์์ ๋์ฒด UI๋ฅผ ํ์ํ๋๋ก ์ํ๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// ์ค๋ฅ๋ฅผ ์ค๋ฅ ๋ณด๊ณ ์๋น์ค์ ๊ธฐ๋กํ ์๋ ์์ต๋๋ค.
console.error(error, errorInfo);
}
render() {
if (this.state.hasError) {
// ์ฌ์ฉ์ ์ ์ ๋์ฒด UI๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค.
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
<ErrorBoundary>
<Suspense fallback={<p>Loading user profile...</p>}>
<MyComponent userId={123} />
</Suspense>
</ErrorBoundary>
SSR ํธํ์ฑ
์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR)๊ณผ ํจ๊ป Suspense๋ฅผ ์ฌ์ฉํ ๋๋ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๊ธฐ ์ ์ ์๋ฒ์์ ๋ฐ์ดํฐ๊ฐ ํ์น๋์๋์ง ํ์ธํด์ผ ํฉ๋๋ค. ์ด๋ react-ssr-prepass์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ์๋์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ํ์นํ์ฌ ์ปดํฌ๋ํธ์ props๋ก ์ ๋ฌํจ์ผ๋ก์จ ๋ฌ์ฑํ ์ ์์ต๋๋ค.
์ ์ญ ์ปจํ ์คํธ์ ๊ตญ์ ํ
๊ธ๋ก๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ฆฌ์์ค ํ์ด ์ธ์ด ์ค์ ์ด๋ ์ฌ์ฉ์ ๊ธฐ๋ณธ ์ค์ ๊ณผ ๊ฐ์ ์ ์ญ ์ปจํ ์คํธ์ ์ด๋ป๊ฒ ์ํธ ์์ฉํ๋์ง ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ํ์น๋ ๋ฐ์ดํฐ๊ฐ ์ ์ ํ๊ฒ ํ์งํ๋์๋์ง ํ์ธํ์ธ์. ์๋ฅผ ๋ค์ด, ์ ํ ์ธ๋ถ ์ ๋ณด๋ฅผ ํ์นํ๋ ๊ฒฝ์ฐ ์ค๋ช ๊ณผ ๊ฐ๊ฒฉ์ด ์ฌ์ฉ์๊ฐ ์ ํธํ๋ ์ธ์ด์ ํตํ๋ก ํ์๋๋๋ก ํด์ผ ํฉ๋๋ค.
์์:
import { useContext } from 'react';
import { LocaleContext } from './LocaleContext';
function ProductComponent({ productId }) {
const { locale, currency } = useContext(LocaleContext);
const productResource = resourcePool.get(`${productId}-${locale}-${currency}`, () =>
fetchProduct(productId, locale, currency)
);
const product = React.use(productResource);
return (
<div>
<h2>{product.name}</h2>
<p>{product.description}</p>
<p>Price: {product.price} {currency}</p>
</div>
);
}
async function fetchProduct(productId, locale, currency) {
// ํ์งํ๋ ์ ํ ๋ฐ์ดํฐ ํ์นญ ์๋ฎฌ๋ ์ด์
await new Promise(resolve => setTimeout(resolve, 500)); // ๋คํธ์ํฌ ์ง์ฐ ์๋ฎฌ๋ ์ด์
const products = {
'123-en-USD': { name: 'Awesome Product', description: 'A fantastic product!', price: 99.99 },
'123-fr-EUR': { name: 'Produit Gรฉnial', description: 'Un produit fantastique !', price: 89.99 },
};
const key = `${productId}-${locale}-${currency}`;
if (products[key]) {
return products[key];
} else {
// ์์ด USD๋ก ํด๋ฐฑ
return products['123-en-USD'];
}
}
์ด ์์์์ LocaleContext๋ ์ฌ์ฉ์๊ฐ ์ ํธํ๋ ์ธ์ด์ ํตํ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ฆฌ์์ค ํค๋ productId, locale, currency๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ฑ๋์ด ์ฌ๋ฐ๋ฅธ ํ์งํ๋ ๋ฐ์ดํฐ๊ฐ ํ์น๋๋๋ก ๋ณด์ฅํฉ๋๋ค. fetchProduct ํจ์๋ ์ ๊ณต๋ ๋ก์ผ์ผ๊ณผ ํตํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์งํ๋ ์ ํ ๋ฐ์ดํฐ๋ฅผ ํ์นํ๋ ๊ฒ์ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค. ํ์งํ๋ ๋ฒ์ ์ด ์๋ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ(์ด ๊ฒฝ์ฐ ์์ด/USD)์ผ๋ก ํด๋ฐฑ๋ฉ๋๋ค.
์ฅ์ ๊ณผ ๋จ์
์ฅ์
- ์ฑ๋ฅ ํฅ์: ์ค๋ณต ๋ฐ์ดํฐ ํ์นญ์ ์ค์ด๊ณ ์ ๋ฐ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ์ค์ ์ง์ค์ ๋ฐ์ดํฐ ๊ด๋ฆฌ: ๋ฐ์ดํฐ์ ๋ํ ๋จ์ผ ์ง์ค ๊ณต๊ธ์์ ์ ๊ณตํ์ฌ ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ์ผ๊ด์ฑ์ ๋จ์ํํฉ๋๋ค.
- ์ ์ธ์ ๋ก๋ฉ ์ํ: Suspense๋ฅผ ์ฌ์ฉํ๋ฉด ์ ์ธ์ ์ด๊ณ ์กฐํฉ ๊ฐ๋ฅํ ๋ฐฉ์์ผ๋ก ๋ก๋ฉ ์ํ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
- ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ: ๋์ ๊ฑฐ์ฌ๋ฆฌ๋ ๋ก๋ฉ ์ํ๋ฅผ ๋ฐฉ์งํ์ฌ ๋ ๋ถ๋๋ฝ๊ณ ๋ฐ์์ฑ์ด ์ข์ ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
๋จ์
- ๋ณต์ก์ฑ: ๋ฆฌ์์ค ํ์ ๊ตฌํํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณต์ก์ฑ์ด ์ถ๊ฐ๋ ์ ์์ต๋๋ค.
- ์บ์ ๊ด๋ฆฌ: ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด ์ ์คํ ์บ์ ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
- ๊ณผ๋ํ ์บ์ฑ ๊ฐ๋ฅ์ฑ: ์ ๋๋ก ๊ด๋ฆฌํ์ง ์์ผ๋ฉด ์บ์๊ฐ ์ค๋๋์ด ์ค๋๋ ๋ฐ์ดํฐ๊ฐ ํ์๋ ์ ์์ต๋๋ค.
๋ฆฌ์์ค ํ์ ๋์
๋ฆฌ์์ค ํ ํจํด์ด ์ข์ ํด๊ฒฐ์ฑ ์ ์ ๊ณตํ์ง๋ง, ํน์ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ๊ณ ๋ คํ ๋ค๋ฅธ ๋์๋ ์์ต๋๋ค:
- Context API: React์ Context API๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํฉ๋๋ค. ์ด๋ ๋ฆฌ์์ค ํ๋ณด๋ค ๊ฐ๋จํ ์ ๊ทผ ๋ฐฉ์์ด์ง๋ง, ๋ฐ์ดํฐ ํ์นญ์ ๋ํ ๋์ผํ ์์ค์ ์ ์ด๋ฅผ ์ ๊ณตํ์ง๋ ์์ต๋๋ค.
- Redux ๋๋ ๊ธฐํ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ: Redux์ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ค์ ์ง์ค์ ์ ์ฅ์์์ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์ด๋ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ข์ ์ต์ ์ ๋๋ค.
- GraphQL ํด๋ผ์ด์ธํธ (์: Apollo Client, Relay): GraphQL ํด๋ผ์ด์ธํธ๋ ์ค๋ณต ํ์นญ์ ํผํ๋ ๋ฐ ๋์์ด ๋๋ ๋ด์ฅ ์บ์ฑ ๋ฐ ๋ฐ์ดํฐ ํ์นญ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค.
๊ฒฐ๋ก
React Suspense ๋ฆฌ์์ค ํ ํจํด์ React ์ ํ๋ฆฌ์ผ์ด์ ์์ ๋ฐ์ดํฐ ๋ก๋ฉ์ ์ต์ ํํ๋ ๊ฐ๋ ฅํ ๊ธฐ์ ์ ๋๋ค. ์ปดํฌ๋ํธ ๊ฐ์ ๋ฐ์ดํฐ ๋ฆฌ์์ค๋ฅผ ๊ณต์ ํ๊ณ ์ ์ธ์ ๋ก๋ฉ ์ํ๋ฅผ ์ํด Suspense๋ฅผ ํ์ฉํจ์ผ๋ก์จ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํค๊ณ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ ์ ์์ต๋๋ค. ์ฝ๊ฐ์ ๋ณต์ก์ฑ์ด ์ถ๊ฐ๋์ง๋ง, ํนํ ๊ณต์ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๊ทธ ์ด์ ์ด ๋น์ฉ์ ๋ฅ๊ฐํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.
๋ฆฌ์์ค ํ์ ๊ตฌํํ ๋ ์บ์ ๋ฌดํจํ, ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ SSR ํธํ์ฑ์ ์ ์คํ๊ฒ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ๋ํ Context API๋ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ์ ๋์์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ํ์ํ์ฌ ํน์ ์๊ตฌ์ ๊ฐ์ฅ ์ ํฉํ ํด๊ฒฐ์ฑ ์ ๊ฒฐ์ ํ์ธ์.
React Suspense์ ๋ฆฌ์์ค ํ ํจํด์ ์์น์ ์ดํดํ๊ณ ์ ์ฉํจ์ผ๋ก์จ, ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ๋ ํจ์จ์ ์ด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋๋ฉฐ ์ฌ์ฉ์ ์นํ์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.